package com.zimmur.service.impl.goods;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.base.Throwables;
import com.zimmur.common.ConstData;
import com.zimmur.dao.goods.IGoodsDao;
import com.zimmur.model.goods.Goods;
import com.zimmur.model.goods.GoodsParameter;
import com.zimmur.model.zone.RecommendHomeGoods;
import com.zimmur.service.RedisCacheUtil;
import com.zimmur.service.goods.IGoodsService;
import com.zimmur.solr.service.ISolrGoodsService;
import com.zimmur.tenpay.util.MD5;
import com.zimmur.tools.PageUtil;

@Service("goodsService")
public class GoodsServiceImpl implements IGoodsService {
	private static Logger log = LoggerFactory.getLogger(GoodsServiceImpl.class);
	
	@Resource
	private IGoodsDao goodsDao;
    
	@Resource
	private ISolrGoodsService solrGoodsService;
	@Resource
	private RedisCacheUtil<Goods> stringRedisDao;
	
	private final static int pageSize = 10;
	
	private final static String REDIS_KEY ="popolook_goods";
	
	private static Object syncLock = new Object();
	
	@Override
	public Goods selectByGoodsId(long goodsId) {
		return goodsDao.selectByPrimaryKey(goodsId);
	}

	@Override
	public List<Goods> selectByGoodsIds(List<Long> goodsIds) {
		Map<String, Object> map = new HashMap<>();
		map.put("goodsIds", goodsIds);
		
		return goodsDao.selectListByGoodsIds(map);
	}
	@Override
	public List<Goods> selectUserCollectionByGoodsIds(Long userId, int curPage) {
		if(curPage == 0)
			curPage = 1;
		int beginIndex = (curPage - 1) *pageSize;
		
		return goodsDao.selectByUserIdGoodsCollectList(userId, beginIndex, pageSize);
	}
	@Override
	public List<Goods> selectRecommandProduct(int topNum) {
		return goodsDao.selectListByRecommand(topNum);
	}

	@Override
	public List<Goods> selectListByTypeIds(GoodsParameter goodsParameter) {
		
		return goodsDao.selectListByTypeIds(goodsParameter);
	}
	
	@Override
	public int selectListByTypeIdsCount(GoodsParameter goodsParameter) {
		return goodsDao.selectListByTypeIdsCount(goodsParameter);
	}
	
	@Override
	public int selectUserIdCountGoods(long userId) {
		return goodsDao.selectUserIdCountGoods(userId);
	}

	@Override
	public int selectByQueryCount(GoodsParameter goodsParameter) {
		return goodsDao.selectByQueryCount(goodsParameter);
	}

	@Override
	public List<Goods> selectBytypeFlagAndTypeIdList(GoodsParameter goodsParameter) {
		return goodsDao.selectBytypeFlagAndTypeIdList(goodsParameter);
	}
	
	@Override
	public int selectBytypeFlagAndTypeIdListCount(GoodsParameter goodsParameter) {
		return goodsDao.selectBytypeFlagAndTypeIdListCount(goodsParameter);
	}
	@Override
	public int updateGoodsNum(Goods goods) {
		return goodsDao.updateGoodsShareNum(goods);
	}

	@Override
	public Goods selectByGoodsIdAndIsCollect(long userId, long goodsId) {
		return goodsDao.selectByGoodsIdAndIsCollect(userId, goodsId);
	}

	@Override
	public boolean updateBrowersNum(Goods goods) {
		boolean flag=false;
		try {
			flag = goodsDao.updateGoodsBrowersNum(goods)>0;
			saveGoodsIdToRedis(goods.getGoodsId());
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}
		return flag;
	}

	@Transactional(propagation=Propagation.REQUIRES_NEW,rollbackFor = {RuntimeException.class,Exception.class})
	public boolean updateInventoryAndSaleAndOrderNum(Goods goods) {
		boolean bret=false;
		try {
			bret = goodsDao.updateGoodsInventoryNumAndSaleNumAndOrdersNum(goods)>0?true:false;
			saveGoodsIdToRedis(goods.getGoodsId());
		}catch (Exception e) {
			bret=false;
			log.error(e.getMessage());
			Throwables.propagate(e);
		}
		return bret;
	}

	@Override
	public List<Goods> selectByGoodsIdsAndTypeFlag(List<Long> goodsIds, Integer typeFlag) {
		List<Goods> goodsList=null;
		String selectByGoodsIdsAndTypeFlag_key = REDIS_KEY+"_"+MD5.MD5Encode(goodsIds.toString()+typeFlag)+"_selectByGoodsIdsAndTypeFlag";
		try {
			Map<String, Object> map = new HashMap<>();
			map.put("goodsIds", goodsIds);
			map.put("typeFlag", typeFlag);
			
			//获取 商品列表
			boolean bRedis = false;
			try {
				bRedis = stringRedisDao.exists(selectByGoodsIdsAndTypeFlag_key);
			} catch (Exception e) {
				log.error(e.getMessage());
			}
			if(bRedis){
				//从缓存中读取
				goodsList = stringRedisDao.getCacheList(selectByGoodsIdsAndTypeFlag_key);
			}else{
				synchronized (syncLock) {
					try {
						bRedis = stringRedisDao.exists(selectByGoodsIdsAndTypeFlag_key);
					} catch (Exception e) {
						log.error(e.getMessage());
					}
					if(bRedis){
						//从缓存中读取
						goodsList = stringRedisDao.getCacheList(selectByGoodsIdsAndTypeFlag_key);
					}else{
						/*缓存中不存在，创建后存入*/
						//从数据库读取
						goodsList = goodsDao.selectByGoodsIdsAndTypeFlag(map);
						try {
							//存入缓存
							stringRedisDao.setCacheList(selectByGoodsIdsAndTypeFlag_key,goodsList);
							stringRedisDao.setTimeout(selectByGoodsIdsAndTypeFlag_key, ConstData.REDIS_KEY_TIMEOUT);
						} catch (Exception e) {
							log.error(e.getMessage());
						}
					}
				}
				
			}			
		} catch (Exception e) {
			log.error(e.getMessage());
		}
		return goodsList;
	}

	@Override
	public List<Goods> selectByDesignerIdTop10(GoodsParameter goodsParameter) {
		return goodsDao.selectListByUserId(goodsParameter);
	}

	@Override
	public List<Goods> selectRecommandProduct(int typeFlag, int pageNow) {
		GoodsParameter parameter=new GoodsParameter();
		if(pageNow==0){
			pageNow = 1;
		}
		parameter.setPageNo(pageNow);
		parameter.setTypeFlag((short)typeFlag);
		
		return goodsDao.selectListByRecommandPage(parameter);
	}

	@Override
	public List<Goods> selectListBytypeFlag(GoodsParameter goodsParameter) {
		return goodsDao.selectListBytypeFlag(goodsParameter);
	}

	@Override
	public int selectListBytypeFlagCount(GoodsParameter goodsParameter) {
		return goodsDao.selectListBytypeFlagCount(goodsParameter);
	}

	@Override
	public List<Goods> selectGoodsListByQuery(GoodsParameter goodsParameter) {
		return goodsDao.selectGoodsListByQuery(goodsParameter);
	}

	@Override
	public int selectGoodsListByQueryCount(GoodsParameter goodsParameter) {
		return goodsDao.selectGoodsListByQueryCount(goodsParameter);
	}

	@Override
	public int selectByDesignerIdAndTypeFlagForZoneRecommandCount(GoodsParameter goodsParameter) {
		return goodsDao.selectListBytypeFlagAndUserIdCount(goodsParameter);
	}

	@Override
	public List<Goods> selectByDesignerIdAndTypeFlagForZoneRecommand(GoodsParameter goodsParameter) {
		return goodsDao.selectListBytypeFlagAndUserId(goodsParameter);
	}

	@Override
	public List<Goods> selectGoodsByParam(GoodsParameter goodsParameter) {
		
		return goodsDao.selectGoodsByParam(goodsParameter);
	}

	@Override
	public int countGoodsByParam(GoodsParameter goodsParameter) {
		
		return goodsDao.countGoodsByParam(goodsParameter);
	}

	@Override
	public PageUtil<com.zimmur.solr.model.Goods> queryGoodsBySolr(GoodsParameter param) {
		PageUtil<com.zimmur.solr.model.Goods> page=solrGoodsService.queryGoods( 
				param.getTypeIds(),param.getTitle(),param.getTags(),param.getTypeFlag(),
				param.getOrderByClause(),param.getOffPercent(),param.getGoodSizeCode(),
				param.getGoodColorName(),param.getPrice(),param.getPageSize(),param.getPageNo());
		
		return page;
	}

	public void saveGoodsIdToRedis(String goodsId){
		boolean isExist=false;
		String goodsIds;
		try {
			isExist=stringRedisDao.exists(ConstData.solr_goodsIds);
			if(isExist){
				goodsIds=stringRedisDao.getCacheString(ConstData.solr_goodsIds);
			}else{
				goodsIds="";
			}
			goodsIds=goodsIds+goodsId+",";
			stringRedisDao.setCacheString(ConstData.solr_goodsIds, goodsIds);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}
	}

	@Override
	public List<RecommendHomeGoods> getRecHomeGoods() {
		return goodsDao.selectRecHomeGoods();
	}
}
